import { Inject, Provide } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typegoose';
import { User } from '../entity/user';
import { RespMethod } from '../util/common.method';
import { RespInfo, RespStatusCode } from '../types/common.type';
import { AuthService } from './auth.service';
import { JwtService } from '@midwayjs/jwt';
import { ReturnModelType } from '@typegoose/typegoose';
import { SexType } from '../types/user.type';
@Provide()
export class UserService {

  @Inject()
  authService: AuthService;

  @Inject()
  jwtService: JwtService;

  @InjectEntityModel(User)
  userModel: ReturnModelType<typeof User>;


  /** 使用用户 uid 获取用户信息 */
  async getUserByUid(uid: string): Promise<RespInfo> {
    const user: User = await this.userModel.findOne({ uid });
    if (user?.uid) {
      const info = JSON.parse(JSON.stringify(user));
      return RespMethod({ info });
    } else {
      return RespMethod({}, RespStatusCode.TokenMiss, '没有找到用户')
    }
  }

  /** 获取访问日志列表 */
  async list(page: number = 0, number: number = 0): Promise<RespInfo> {
    const list = await this.userModel.find({}).skip((page - 1) * number).limit(number).sort([['created', -1]])
    const total = (await this.userModel.find({})).length;
    return RespMethod({ list, total, page: Math.ceil(total / number) })
  }

  /** 使用 token 获取用户信息 */
  async getUserByToken(token: string): Promise<RespInfo> {
    const { data, code, message } = this.authService.decode(token);
    if (code) {
      return RespMethod(data, code, message)
    } else {
      return await this.getUserByUid(data.uid);
    }
  }

  /**
   * 邮箱密码方式登录 
   * @param email 
   * @param password 
   * @returns 
   */
  async login(email: string, password: string): Promise<RespInfo> {
    if (await this.userModel.findOne({ email })) {
      const user = await this.userModel.findOne({ email, password })
      if (user?.uid) {
        const token = this.authService.sign(user.uid)
        return RespMethod({ token });
      } else {
        return RespMethod({}, RespStatusCode.Error, '密码错误')
      }
    } else {
      return RespMethod({}, RespStatusCode.Error, '没有找到此账号');
    }
  }

  /**
   * 用户注册
   * @param password 密码
   * @param secret 秘钥（包含 邮箱，及邮箱验证码）
   * @param inputCode 验证码
   * @returns 
   */
  async register(password: string, secret: string, inputCode: string): Promise<RespInfo> {
    const { code, email } = this.jwtService.decodeSync(secret) as any;
    if (code.toLowerCase() == inputCode.toLowerCase()) {
      if (await this.userModel.findOne({ email })) {
        return RespMethod({}, RespStatusCode.Error, '该邮箱已被注册')
      } else {
        const user = await this.userModel.create({ email, password })
        return RespMethod({ token: this.authService.sign(user.uid) })
      }
    } else {
      return RespMethod({}, RespStatusCode.Error, '验证码错误')
    }
  }

  async forgotpassword(password: string, secret: string, inputCode: string): Promise<RespInfo> {
    const { code, email } = this.jwtService.decodeSync(secret) as any;
    if (code.toLowerCase() == inputCode.toLowerCase()) {
      if (!await this.userModel.findOne({ email })) {
        return RespMethod({}, RespStatusCode.Error, '该邮箱未注册')
      } else {
        await this.userModel.updateOne({ password }).where({ email });
        const user = await this.userModel.findOne({ email })
        return RespMethod({ token: this.authService.sign(user.uid) })
      }
    } else {
      return RespMethod({}, RespStatusCode.Error, '验证码错误')
    }
  }

  /** 修改用户基础信息 */
  async updated(uid: string, avatar: string, name: string, nick: string, birthday: number, motto: string, sex: SexType): Promise<RespInfo> {
    await this.userModel.updateOne({ avatar, name, nick, birthday, motto, sex }).where({ uid });
    return await this.getUserByUid(uid);
  }

  /** 修改用户基础信息 */
  async updatedPassword(uid: string, oldpsw: string, newpsw: string): Promise<RespInfo> {
    if (await this.userModel.findOne({ uid, password: oldpsw })) {
      await this.userModel.updateOne({ password: newpsw }).where({ uid });
      return RespMethod({});
    }
    return RespMethod({}, RespStatusCode.Error, '原密码错误');
  }
}
